// part1:C13:ex13.28.cpp
#include <iostream>
#include <string>
class TreeNode
{
public:
  TreeNode():
    value(""), count(1), left(nullptr), right(nullptr){}
  // TreeNode(const std::string &s = std::string(),
  //   TreeNode *lchild = nullptr, TreeNode *right = nullptr):
  //    value(s), count(1), left(lchild), right(rchild){}
  TreeNode(const TreeNode &tn):
    (tn.value), count(1), left(tn.left), right(tn.right);
  ~TreeNode();
  void CopyTree(void);
  int ReleaseTree(void);
private:
  std::string value;
  int count;
  TreeNode *left;
  TreeNode *right;
};

// TreeNode::TreeNode(const string &s = string(),
//     TreeNode *lchild = nullptr, TreeNode *right = nullptr):
//   value(s), count(1), left(lchild), right(rchild){}

void TreeNode::CopyTree(void)
{
  if (left)
  {
    left->CopyTree();
  }

  if (right)
  {
    right->CopyTree();
  }
  count++;
}

// copy child tree from a node.
TreeNode::TreeNode(const TreeNode &tn):
  value(tn.value), count(1), left(tn.left), right(tn.right)
{
  if (left)
  {
    left->CopyTree();
  }

  if (right)
  {
    right->CopyTree();
  }
}

int TreeNode::ReleaseTree(void)
{
  if (left)
  {
    if (!left->CopyTree())
    {
      delete left;
    }
  }

  if (right)
  {
    if (!right->CopyTree())
    {
      delete right;
    }
  }
  count--;
  return count;
}

TreeNode::~TreeNode()
{
  // count is zero, means resouce has released.
  if (count)
  {
    ReleaseTree();
  }
}

class BinStrTree
{
public:
  BinStrTree(): root(nullptr){}
  BinStrTree(TreeNode *t = nullptr): root(t){};
  BinStrTree(const BinStrTree &bst): root(bst.root)
  {
    root->CopyTree();
  };
  ~BinStrTree();
private:
  TreeNode *root;
};

// BinStrTree::BinStrTree(TreeNode *t = nullptr): root(t){}

// BinStrTree::BinStrTree(const BinStrTree &bst): root(bst.root)
// {
//   root->CopyTree();
// }

BinStrTree::~BinStrTree()
{
  if (!root->ReleaseTree())
  {
    delete root;
  }
}